
	/************************************************************************
	*	HISR - Keypad
	*	
	*	@brief	- checks if keypad interrupt
	*			- sets corresponding flags (or values) depending on key press
	*
	*	@author		Felix Ossig-Bonanno
	*	@file       hisr_keypad.c
	*	@ver		1.0 (initial keypad release)
	*
	*************************************************************************/

#include <p18f452.h>
#include <string.h>
#include "hisr_keypad.h"
#include "globals.h"

unsigned char key2char[] = {'1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D'};//depending on how keypad is wired to board
void clear_Dispflags(void);//decleration - function clears all the Display Flags
void key_interpret(void);//main function which acts on input

///////////////////////////////////
//basic commands are initialised in the header

//initialise advanced comands (need to be variables so that they have an address)(commands set in header)
const unsigned char _ADV_CMD_FACTORY[] 					= ADV_CMD_FACTORY;	//code for factory mode
const unsigned char _ADV_CMD_USER[] 					= ADV_CMD_USER;		//etc.
const unsigned char _ADV_CMD_SAMPLES_PER_MEASURMENT[] 	= ADV_CMD_SAMPLES_PER_MEASURMENT;
const unsigned char _ADV_CMD_TIME_BETWEEN_SAMPLES[] 	= ADV_CMD_TIME_BETWEEN_SAMPLES;
const unsigned char _ADV_CMD_RANGE_GATE[] 				= ADV_CMD_RANGE_GATE;
const unsigned char _ADV_CMD_SHOW_RANGE_READINGS[] 		= ADV_CMD_SHOW_RANGE_READINGS;
const unsigned char _ADV_CMD_SHOW_STATISTICS[] 			= ADV_CMD_SHOW_STATISTICS;
const unsigned char _ADV_CMD_TEMP_CELCIUS[] 			= ADV_CMD_TEMP_CELCIUS;
const unsigned char _ADV_CMD_TEMP_FARENHEIT[] 			= ADV_CMD_TEMP_FARENHEIT;
///////////////////////////////////

unsigned char adv_cmd[ADV_CMD_MAXLEN+1];	//array to store adv command
unsigned char* adv_cmd_p = adv_cmd;			//pointer to adv command
unsigned short adv_cmd_flag = 0;			//determines whether inputs should be treated as advanced commands

void init_keypad(void){
///////////////////////////////////////////////////////
//Setup for the selected external interupt source
///////////////////////////////////////////////////////
	#ifdef INT0 //INT0 (NOTE: always high priority)
		//Configure INT0
			INTCONbits.INT0IF = 0;		//ensure flag cleared
			INTCON2bits.INTEDG0 = 1;	//interupt on rising edge
			TRISB |= 0b00000001;		//pin as input
			
			INTCONbits.INT0IE = 1;		//enable interrupt
	#endif
	
	#ifdef INT1 //INT1
		//Configure INT1
			INTCON3bits.INT1IF = 0;		//ensure flag cleared
			INTCON2bits.INTEDG1 = 1;	//interrupt on rising edge
			INTCON3bits.INT1IP = 1;		//set priority as high
			TRISB |= 0b00000010;		//pin as input
			
			INTCON3bits.INT1IE = 1;		//enable interrupt
	#endif
	
	#ifdef INT2	//INT2
		//Configure INT2
			INTCON3bits.INT2IF = 0;		//ensure flag cleared
			INTCON2bits.INTEDG2 = 1;	//interrupt on rising edge
			INTCON3bits.INT2IP = 1;		//set priority as high
			TRISB |= 0b00000100;		//pin as input
			
			INTCON3bits.INT2IE = 1;		//enable interrupt
	#endif
///////////////////////////////////////////////////////

	//Configure data input pins
	TRISB |= INPUTMASK;
///////////////////////////////////////////////////////
}



void hisr_keypad(void){
///////////////////////////////////////////////////////
//checks if key pressed. i.e. if interrupt triggered by keypad
///////////////////////////////////////////////////////

	//Check if interrupt triggered by keypad
	#ifdef INT0
		if (INTCONbits.INT0IF)
			key_interpret();
	#endif
	#ifdef INT1
		if (INTCON3bits.INT1IF)
			key_interpret();
	#endif
	#ifdef INT2
		if (INTCON3bits.INT2IF)
			key_interpret();
	#endif	

	//////////////////////////////////////////////

	//Clear interrupt flag
	#ifdef INT0
		INTCONbits.INT0IF = 0;
	#endif
	#ifdef INT1
		INTCON3bits.INT1IF = 0;
	#endif
	#ifdef INT2
		INTCON3bits.INT2IF = 0;
	#endif

}


void key_interpret(void){
///////////////////////////////////////////////////////
//processes the pressed key(s)
///////////////////////////////////////////////////////

	unsigned char input;
	
	//get character from keypad
	input = key2char[(PORTB &= INPUTMASK)>> N];
	

	if (adv_cmd_flag == 0)//if not entering advanced commands
	{
		///////////////////////
		// check basic command
		///////////////////////
		switch ((int)input)
		{
			case CMD_ADVANCED: //enable adv cmds
			{	
				adv_cmd_flag = 1; 
				break;
			}
			case CMD_SHOW_MODE:
			{
				clear_Dispflags();
				Dispflags.mode ^= 1;
				break;
			}
			case CMD_SHOW_DIST:
			{
				clear_Dispflags();
				Dispflags.dist = 1;
				Stateflags.single = 1;
				break;
			}
			case CMD_SHOW_TEMP:
			{
				clear_Dispflags();
				Dispflags.temp = 1;
				Stateflags.single = 1;
				break;
			}
			case CMD_METRIC:
			{
				Stateflags.metric ^= 1;
				break;
			}
			case CMD_CONTINUOUS:
			{
				Stateflags.continuous ^= 1;
				break;
			}
			//default:
				//assert(INVALID KEY);	//impossible //not available in MPLAB?
			
		}
	}
	else// take commands in factory mode
	{
		*adv_cmd_p++ = input;
		
		
		if((adv_cmd_p >= (adv_cmd + ADV_CMD_MAXLEN))||(input == '*'))
		{
			*adv_cmd_p = '\0';
			adv_cmd_p = adv_cmd; //reset pointer
			
			if(input != '*')
			{
				adv_cmd_flag = 0; //return to simple command interface
				
				////////////////////
				//check adv command
				////////////////////
				if 		(strcmp(adv_cmd, _ADV_CMD_FACTORY)==0)
					Stateflags.user = 0;
				else if (strcmp(adv_cmd, _ADV_CMD_USER)==0)
					Stateflags.user = 1;
				else if (strcmp(adv_cmd, _ADV_CMD_SAMPLES_PER_MEASURMENT)==0)
					;//FIX - not implemented
				else if (strcmp(adv_cmd, _ADV_CMD_TIME_BETWEEN_SAMPLES)==0)
					;//FIX - not implemented
				else if (strcmp(adv_cmd, _ADV_CMD_RANGE_GATE)==0)
					;//FIX - not implemented
				else if (strcmp(adv_cmd, _ADV_CMD_SHOW_RANGE_READINGS)==0)
					Dispflags.range_rds = 1;
				else if (strcmp(adv_cmd, _ADV_CMD_SHOW_STATISTICS)==0)
					Dispflags.stats = 1;
				else if (strcmp(adv_cmd, _ADV_CMD_TEMP_CELCIUS)==0)
					Stateflags.celcius = 1;
				else if (strcmp(adv_cmd, _ADV_CMD_TEMP_FARENHEIT)==0)
					Stateflags.celcius = 0;
				
				
			}
			
		}
	}
}


void clear_Dispflags(void){
///////////////////////////////////////////////////////
//Clears all Display Flags. Used since only one output displayed at a time
///////////////////////////////////////////////////////

	Dispflags.mode = Dispflags.dist = Dispflags.temp = Dispflags.range_rds = Dispflags.stats = 0;
}